<template>
  <div class="file-upload">
    <el-upload
      ref="uploadRef"
      v-bind="uploadProps"
      :action="action"
      :headers="headers"
      :multiple="multiple"
      :file-list="fileList"
      :before-upload="handleBeforeUpload"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-progress="handleProgress"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :on-preview="handlePreview"
      :drag="drag"
      :accept="accept"
      :disabled="disabled"
      :limit="limit"
      :show-file-list="showFileList"
    >
      <template #trigger>
        <slot name="trigger">
          <el-button type="primary" :disabled="disabled">
            <el-icon><Upload /></el-icon>
            {{ buttonText }}
          </el-button>
        </slot>
      </template>
      
      <template #tip>
        <slot name="tip">
          <div class="upload-tip" v-if="tip">
            {{ tip }}
          </div>
        </slot>
      </template>
      
      <template #default>
        <slot>
          <div class="upload-drag-area" v-if="drag">
            <el-icon class="upload-icon"><Upload /></el-icon>
            <div class="upload-text">
              <span>将文件拖到此处，或</span>
              <el-button type="primary" link>点击上传</el-button>
            </div>
          </div>
        </slot>
      </template>
    </el-upload>
    
    <!-- 图片预览 -->
    <image-preview
      v-if="previewUrl"
      :url="previewUrl"
      :visible="previewVisible"
      @update:visible="previewVisible = $event"
    />
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { Upload } from '@element-plus/icons-vue'
import { getToken } from '@/utils/auth'
import ImagePreview from '@/components/ImagePreview/index.vue'

const props = defineProps({
  // 上传地址
  action: {
    type: String,
    required: true
  },
  // 是否多选
  multiple: {
    type: Boolean,
    default: false
  },
  // 是否拖拽上传
  drag: {
    type: Boolean,
    default: false
  },
  // 文件类型限制
  accept: {
    type: String,
    default: ''
  },
  // 文件大小限制（MB）
  maxSize: {
    type: Number,
    default: 10
  },
  // 文件数量限制
  limit: {
    type: Number,
    default: 0
  },
  // 是否显示文件列表
  showFileList: {
    type: Boolean,
    default: true
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 按钮文字
  buttonText: {
    type: String,
    default: '点击上传'
  },
  // 提示文字
  tip: {
    type: String,
    default: ''
  },
  // 文件列表
  modelValue: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['update:modelValue', 'success', 'error', 'remove', 'exceed'])

// 上传组件引用
const uploadRef = ref(null)

// 文件列表
const fileList = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

// 上传配置
const uploadProps = computed(() => ({
  name: 'file',
  headers: {
    Authorization: `Bearer ${getToken()}`
  }
}))

// 预览相关
const previewVisible = ref(false)
const previewUrl = ref('')

// 处理上传前校验
const handleBeforeUpload = (file) => {
  // 校验文件大小
  const isLtMaxSize = file.size / 1024 / 1024 < props.maxSize
  if (!isLtMaxSize) {
    ElMessage.error(`文件大小不能超过 ${props.maxSize}MB!`)
    return false
  }
  
  // 校验文件类型
  if (props.accept) {
    const extension = file.name.split('.').pop().toLowerCase()
    const acceptTypes = props.accept.split(',').map(type => 
      type.trim().replace('.', '').toLowerCase()
    )
    
    if (!acceptTypes.includes(extension)) {
      ElMessage.error(`只能上传 ${props.accept} 格式的文件!`)
      return false
    }
  }
  
  return true
}

// 处理上传成功
const handleSuccess = (response, file, fileList) => {
  if (response.code === 200) {
    ElMessage.success('上传成功')
    emit('success', { response, file, fileList })
  } else {
    ElMessage.error(response.message || '上传失败')
    emit('error', { response, file, fileList })
  }
}

// 处理上传失败
const handleError = (error, file, fileList) => {
  ElMessage.error('上传失败')
  emit('error', { error, file, fileList })
}

// 处理上传进度
const handleProgress = (event, file, fileList) => {
  console.log('上传进度：', event.percent)
}

// 处理移除文件
const handleRemove = (file, fileList) => {
  emit('remove', { file, fileList })
}

// 处理超出限制
const handleExceed = (files, fileList) => {
  ElMessage.warning(`最多只能上传 ${props.limit} 个文件`)
  emit('exceed', { files, fileList })
}

// 处理预览
const handlePreview = (file) => {
  if (file.url) {
    previewUrl.value = file.url
    previewVisible.value = true
  }
}

// 手动上传
const submit = () => {
  uploadRef.value?.submit()
}

// 清空文件列表
const clearFiles = () => {
  uploadRef.value?.clearFiles()
}

// 暴露方法
defineExpose({
  submit,
  clearFiles
})
</script>

<style lang="scss" scoped>
.file-upload {
  .upload-tip {
    font-size: 12px;
    color: #909399;
    margin-top: 8px;
  }
  
  .upload-drag-area {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 200px;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    transition: border-color 0.3s;
    
    &:hover {
      border-color: #409EFF;
    }
    
    .upload-icon {
      font-size: 48px;
      color: #c0c4cc;
      margin-bottom: 16px;
    }
    
    .upload-text {
      color: #606266;
      
      .el-button {
        margin-left: 4px;
      }
    }
  }
}
</style> 